package cn.com.tuns.assess.qsb.frame.ui;

import android.content.Context;
import android.os.Looper;
import android.provider.Settings;
import cn.com.tuns.assess.qsb.frame.util.LogUtil;

import java.io.FileInputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Properties;
import java.util.UUID;


/**
 * UncaughtExceptionHandler：线程未捕获异常控制器是用来处理未捕获异常的。 如果程序出现了未捕获异常默认情况下则会出现强行关闭对话框 实现该接口并注册为程序中的默认未捕获异常处理 这样当未捕获异常发生时，就可以做些异常处理操作 例如：收集异常信息，发送错误报告 等。
 * <p/>
 * UncaughtException处理类,当程序发生Uncaught异常的时候,由该类来接管程序,并记录发送错误报告.
 */
public class MyCrashHanlder implements UncaughtExceptionHandler {
  /** Debug Log Tag */
  /** 是否开启日志输出, 在Debug状态下开启, 在Release状态下关闭以提升程序性能 */
  /**
   * CrashHandler实例
   */
  private static MyCrashHanlder instance;
  /**
   * 程序的Context对象
   */
  private Context mContext;
  /**
   * 系统默认的UncaughtException处理类
   */
  private UncaughtExceptionHandler mDefaultHandler;

  /**
   * 使用Properties来保存设备的信息和错误堆栈信息
   */
  private Properties mDeviceCrashInfo = new Properties();
  private static final String VERSION_NAME = "versionName";
  private static final String VERSION_CODE = "versionCode";
  private static final String STACK_TRACE = "ERROR";
  /**
   * 错误报告文件的扩展名
   */
  private static final String CRASH_REPORTER_EXTENSION = ".log";

  /**
   * 保证只有一个CrashHandler实例
   */
  private MyCrashHanlder() {
  }

  /**
   * 获取CrashHandler实例 ,单例模式
   */
  public static MyCrashHanlder getInstance() {
    if (instance == null) {
      instance = new MyCrashHanlder();
    }
    return instance;
  }

  /**
   * 初始化,注册Context对象, 获取系统默认的UncaughtException处理器, 设置该CrashHandler为程序的默认处理器
   */
  public void init(Context ctx) {
    mContext = ctx;
    mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
    Thread.setDefaultUncaughtExceptionHandler(this);
  }

  /**
   * 当UncaughtException发生时会转入该函数来处理
   */
  public void uncaughtException(Thread thread, Throwable ex) {
    if (!handleException(ex) && mDefaultHandler != null) {
      // 如果用户没有处理则让系统默认的异常处理器来处理
      mDefaultHandler.uncaughtException(thread, ex);
    } else {
      // Sleep一会后结束程序
      // 来让线程停止一会是为了显示Toast信息给用户，然后Kill程序
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      try {
//                Intent intent1 = new Intent(mContext, MainActivity.class);   //主页面
//                PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent1, 0);
//                AlarmManager mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
//                mAlarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 500, pendingIntent);
        BaseActivity.exit();
//                    System.exit(0);//退出程序

      } catch (Exception e) {
        e.printStackTrace();
      }
      android.os.Process.killProcess(android.os.Process.myPid());
      System.exit(0);
    }
  }

  /**
   * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. 开发者可以根据自己的情况来自定义异常处理逻辑
   *
   * @return true:如果处理了该异常信息;否则返回false
   */
  private boolean handleException(Throwable ex) {
    if (ex == null) {
      return true;
    }
    ex.printStackTrace();
    final String msg = ex.getLocalizedMessage();
    // 使用Toast来显示异常信息
    new Thread() {
      @Override
      public void run() {
        // Toast 显示需要出现在一个线程的消息队列中
        Looper.prepare();
        // SlookToast.showToast(mContext, " 出错啦 ！ " + msg);
        Looper.loop();
      }
    }.start();
    // 收集设备信息
    // collectCrashDeviceInfo(mContext);
    // 保存错误报告文件
//    String crashFileName = saveCrashInfoToFile(ex);
    LogUtil.saveCrashInfo2File(ex);

//    AppManage.isLogin=false;
//    AppManage.saveLoginData();
    // 发送错误报告到服务器
//    sendCrashReportsToServer(mContext);
    return true;
  }

//  /**
//   * 收集程序崩溃的设备信息
//   */
//  public void collectCrashDeviceInfo(Context ctx) {
//    try {
//      // Class for retrieving various kinds of information related to the
//      // application packages that are currently installed on the device.
//      // You can find this class through getPackageManager().
//      PackageManager pm = ctx.getPackageManager();
//      // getPackageInfo(String packageName, int flags)
//      // Retrieve overall information about an application package that is
//      // installed on the system.
//      // public static final int GET_ACTIVITIES
//      // Since: API Level 1 PackageInfo flag: return information about
//      // activities in the package in activities.
//      PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(),
//          PackageManager.GET_ACTIVITIES);
//      if (pi != null) {
//        // public String versionName The version name of this package,
//        // as specified by the <manifest> tag's versionName attribute.
//        mDeviceCrashInfo.put(VERSION_NAME,
//            pi.versionName == null ? "not set" : pi.versionName);
//        // public int versionCode The version number of this package,
//        // as specified by the <manifest> tag's versionCode attribute.
//        mDeviceCrashInfo.put(VERSION_CODE, pi.versionCode);
//      }
//    } catch (NameNotFoundException e) {
//    }
//    // 使用反射来收集设备信息.在Build类中包含各种设备信息,
//    // 例如: 系统版本号,设备生产商 等帮助调试程序的有用信息
//    // 返回 Field 对象的一个数组，这些对象反映此 Class 对象所表示的类或接口所声明的所有字段
//    Field[] fields = Build.class.getDeclaredFields();
//    for (Field field : fields) {
//      try {
//        // setAccessible(boolean flag)
//        // 将此对象的 accessible 标志设置为指示的布尔值。
//        // 通过设置Accessible属性为true,才能对私有变量进行访问，不然会得到一个IllegalAccessException的异常
//        field.setAccessible(true);
//        mDeviceCrashInfo.put(field.getName(), field.get(null));
//      } catch (Exception e) {
//      }
//    }
//  }

//  /**
//   * 保存错误信息到文件中
//   */
//  private String saveCrashInfoToFile(Throwable ex) {
//
//    Writer info = new StringWriter();
//    PrintWriter printWriter = new PrintWriter(info);
//    // printStackTrace(PrintWriter s)
//    // 将此 throwable 及其追踪输出到指定的 PrintWriter
//    ex.printStackTrace(printWriter);
//    ex.printStackTrace();
//    // getCause() 返回此 throwable 的 cause；如果 cause 不存在或未知，则返回 null。
//    Throwable cause = ex.getCause();
//    while (cause != null) {
//      cause.printStackTrace(printWriter);
//      cause = cause.getCause();
//    }
//
//    // toString() 以字符串的形式返回该缓冲区的当前值。
//
//    String result = getErrorInfo(ex);
//    String time = System.currentTimeMillis() + "";
//    printWriter.close();
//    mDeviceCrashInfo.put(STACK_TRACE, result);
//
//    try {
//      String fileName = "error-" + time + CRASH_REPORTER_EXTENSION;
//      // 保存文件
//      FileOutputStream trace = mContext.openFileOutput(fileName,
//          MODE_PRIVATE);
////			mDeviceCrashInfo.store(trace, "");
//      trace.write(result.getBytes());
//      trace.flush();
//      trace.close();
//      return fileName;
//    } catch (Exception e) {
//      e.printStackTrace();
//    }
//    return null;
//  }

  /**
   * 　　* 获取错误的信息 　　* @param arg1 　　* @return
   */
  private String getErrorInfo(Throwable arg1) {
    Writer writer = new StringWriter();
    PrintWriter pw = new PrintWriter(writer);
    arg1.printStackTrace(pw);
    pw.close();
    String error = writer.toString();
    return error;
  }


  /**
   * 将文件转化为字符串
   *
   * @author Jacen
   * @email jacen@wscnydx.com
   * @datetime @2015-11-11下午7:56:20
   */
  public static String readStringForFile(String path) {
    String res = "";
    try {
      FileInputStream is = new FileInputStream(path);
      int length = is.available();
      byte[] buffer = new byte[length];
      is.read(buffer);
      res = new String(buffer, "UTF-8");
      is.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return res;
  }


  /**
   * 得到全局唯一UUID
   */
  public static String getDeviceUUid() {
    String androidId = MyCrashHanlder.getAndroidID();
    UUID deviceUuid = new UUID(androidId.hashCode(), ((long) androidId.hashCode() << 32));
    return deviceUuid.toString();
  }

  //获取ANDROID_ID
  public static String getAndroidID() {
    String id = Settings.Secure.getString(
        MyApplication.context.getContentResolver(),
        Settings.Secure.ANDROID_ID
    );
    return id == null ? "" : id;
  }


}
